package com.mapbar.ure.backend.converter;

import java.util.List;

import com.mapbar.ure.backend.NFA;
import com.mapbar.ure.frontend.parser.AST;

/**
 * 利用Thompson构造法构建NFA
 * 
 * 由于与RE耦合高，单独提出，避免影响前端的解析器独立性。
 * 
 * 
 * 考虑到语法检测应该在AST转化过程中有过，这里不涉及任何语法的非法性检测。
 * 
 * 可能会有语义层面的错误，考虑到RE的简单性，放弃检查。
 * 
 * @author QIN Jian
 * 
 */
public class REAST2NFAConverter<T> {
	public NFA<T> convert(AST<T> ast) {
		List<AST<T>> children = ast.getChildren();
		if (children == null) {
			return new NFA<T>(ast.getValue());
		}
		switch (children.size()) {
		case 2:
			return makeNode2(children.get(0), children.get(1));
		case 3:
			return makeNode3(children.get(1), children.get(2), children.get(0));
		default:
			return null;
		}
	}

	private NFA<T> makeNode3(AST<T> op, AST<T> v0, AST<T> v1) {
		switch (op.getType()) {
		case Cons:
			return consNFA(convert(v0), convert(v1));
		case Or:
			return orNFA(convert(v0), convert(v1));
		default:
			// 括号的情况 ( RE ) , 没有操作符。
			return convert(op);
		}
	}

	private NFA<T> orNFA(NFA<T> node0, NFA<T> node1) {
		return node0.or(node1);
	}

	private NFA<T> consNFA(NFA<T> node0, NFA<T> node1) {
		return node0.cons(node1);
	}

	private NFA<T> makeNode2(AST<T> op, AST<T> v) {
		switch (op.getType()) {
		case Closure:
			return closureNFA(convert(v));
		default:
			return null;
		}
	}

	private NFA<T> closureNFA(NFA<T> func) {
		return func.closure();
	}

}
